package com.sayice.robotconflict.view.control

import androidx.compose.foundation.*
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.*
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.painter.ColorPainter
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import com.sayice.robotconflict.ui.screen.cdp
import kotlin.math.roundToInt
import kotlin.time.DurationUnit
import kotlin.time.toDuration

/**
 * 时间显示
 *
 * @param millis 时长 (毫秒)
 * @param modifier 修改器
 * @param color 颜色
 * @param fontSize 文字大小
 */
@Composable
fun TimeDisplay(
    millis: Int,
    modifier: Modifier = Modifier,
    color: Color = Color.Unspecified,
    fontSize: TextUnit = TextUnit.Unspecified
) {
    val text = millis.toDuration(DurationUnit.MILLISECONDS).toComponents { minutes, seconds, _ ->
        String.format("%02d:%02d", minutes, seconds)
    }
    Text(text = text, modifier = modifier, color = color, fontSize = fontSize)
}

/**
 * 控制切换按钮组
 *
 * @param modifier 修饰符
 * @param elements 元素
 * @param selected 选中的元素
 * @param buttonSize 元素按钮大小
 * @param space 元素按钮间距
 * @param borderWidth 边框宽度
 * @param onClick 元素点击回调，参数为当前选中的元素，null表示没有选中任何元素
 */
@Composable
fun <T> ControlButtons(
    modifier: Modifier = Modifier,
    elements: List<T>,
    selected: T? = null,
    buttonSize: Dp = 100.dp,
    space: Dp = 10.dp,
    borderWidth: Dp = 2.dp,
    onClick: (current: T?) -> Unit
) {
    Column(modifier = modifier, verticalArrangement = Arrangement.spacedBy(space)) {
        if (elements.isNotEmpty()) {
            for (element in elements) {
                Image(
                    painter = ColorPainter(Color.Blue), contentDescription = null,
                    alpha = 0.5f,
                    modifier = Modifier
                        .clip(CircleShape)
                        .size(buttonSize)
                        .border(
                            if (element == selected) borderWidth else 0.dp,
                            Color.Blue,
                            CircleShape
                        )
                        .clickable { onClick(if (element == selected) null else element) }
                )
            }
        }
    }
}

/**
 * 摇杆
 *
 * @param modifier 修饰符
 * @param size 大小
 * @param borderWidth 边框宽度
 * @param onDragStart 开始拖动回调
 * @param onDragEnd 结束拖动回调
 * @param onDrag 拖动回调
 */
@Composable
fun JoyStick(
    modifier: Modifier = Modifier,
    size: Dp = 100.dp,
    borderWidth: Dp = 2.dp,
    onDragStart: (Offset) -> Unit = { },
    onDragEnd: () -> Unit = { },
    onDrag: (Offset, length: Float) -> Unit = { _, _ -> }
) {
    Box(
        modifier = modifier
            .size(size)
            .border(borderWidth, Color.Blue, CircleShape)
    ) {
        var offset by remember { mutableStateOf(Offset.Zero) }
        var fingerOffset = Offset.Zero
        Image(painter = ColorPainter(Color.Blue), contentDescription = null,
            modifier = Modifier
                .align(Alignment.Center)
                .offset { IntOffset(offset.x.roundToInt(), offset.y.roundToInt()) }
                .clip(CircleShape)
                .size(size / 4)
                .pointerInput(Unit) {
                    detectDragGestures(
                        onDragStart = onDragStart,
                        onDragEnd = {
                            fingerOffset = Offset.Zero
                            offset = Offset.Zero
                            onDragEnd()
                        }
                    ) { _, dragAmount ->
                        fingerOffset += dragAmount
                        val radius = size.toPx() / 2
                        val distance = fingerOffset.getDistance()
                        offset = if (distance > radius) {
                            onDrag(offset, radius)
                            fingerOffset / (distance / radius)
                        } else {
                            onDrag(offset, distance)
                            fingerOffset
                        }
                    }
                }
        )
    }
}

/**
 * 字符串选择框
 *
 * @param strList 字符串列表
 * @param width 宽度
 * @param height 高度
 * @param onDismissRequest 对话框关闭回调
 * @param onSelect 列表项选择回调
 */
@Composable
fun StrSelectDialog(
    strList: List<String>,
    width: Dp,
    height: Dp,
    onDismissRequest: () -> Unit,
    onSelect: (String) -> Unit
) {
    var searchedName by remember { mutableStateOf("") }
    Dialog(onDismissRequest = onDismissRequest) {
        Column(
            modifier = Modifier
                .size(width, height)
                .background(Color.White)
                .padding(10.cdp), horizontalAlignment = Alignment.CenterHorizontally
        ) {
            TextField(value = searchedName, onValueChange = { searchedName = it })
            Spacer(modifier = Modifier.height(50.cdp))
            LazyColumn(verticalArrangement = Arrangement.spacedBy(10.cdp)) {
                items(strList) { name ->
                    if (name.contains(searchedName, ignoreCase = true)) {
                        Row(modifier = Modifier
                            .fillMaxWidth()
                            .clickable { onSelect(name) }) {
                            Text(name)
                        }
                    }
                }
            }
        }
    }
}

/**
 * 确定/取消按钮
 *
 * @param modifier 修改器
 * @param onConfirm 确定按钮点击回调
 * @param onCancel 取消按钮点击回调
 * @param confirmName 确定按钮显示的名字
 * @param cancelName 取消按钮显示的名字
 */
@Composable
fun ConfirmAndCancelButton(
    modifier: Modifier = Modifier,
    onConfirm: () -> Unit,
    onCancel: () -> Unit,
    confirmName: String = "确定",
    cancelName: String = "取消"
) {
    Row(
        modifier = modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.SpaceAround,
        verticalAlignment = Alignment.CenterVertically
    ) {
        Button(
            onClick = onCancel,
            modifier = Modifier.defaultMinSize(1.dp, 1.dp),
            contentPadding = PaddingValues(
                horizontal = 10.cdp,
                vertical = 2.cdp
            )
        ) {
            Text(cancelName)
        }
        Button(
            onClick = onConfirm,
            modifier = Modifier.defaultMinSize(1.dp, 1.dp),
            contentPadding = PaddingValues(horizontal = 10.cdp, vertical = 2.cdp)
        ) {
            Text(confirmName)
        }
    }
}

/**
 * 自定义按钮，增加了长按和双击监听
 */
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun CustomButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    onLongClick: (() -> Unit)? = null,
    onDoubleClick: (() -> Unit)? = null,
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    elevation: ButtonElevation? = ButtonDefaults.elevation(),
    shape: Shape = MaterialTheme.shapes.small,
    border: BorderStroke? = null,
    colors: ButtonColors = ButtonDefaults.buttonColors(),
    contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
    content: @Composable RowScope.() -> Unit
) {
    val contentColor by colors.contentColor(enabled)
    Surface(
        modifier = modifier.combinedClickable(
            interactionSource = interactionSource,
            indication = rememberRipple(),
            enabled = enabled,
            role = Role.Button,
            onClick = onClick,
            onLongClick = onLongClick,
            onDoubleClick = onDoubleClick
        ),
        shape = shape,
        color = colors.backgroundColor(enabled).value,
        contentColor = contentColor.copy(alpha = 1f),
        border = border,
        elevation = elevation?.elevation(enabled, interactionSource)?.value ?: 0.dp
    ) {
        CompositionLocalProvider(LocalContentAlpha provides contentColor.alpha) {
            ProvideTextStyle(
                value = MaterialTheme.typography.button
            ) {
                Row(
                    Modifier
                        .defaultMinSize(
                            minWidth = ButtonDefaults.MinWidth,
                            minHeight = ButtonDefaults.MinHeight
                        )
                        .padding(contentPadding),
                    horizontalArrangement = Arrangement.Center,
                    verticalAlignment = Alignment.CenterVertically,
                    content = content
                )
            }
        }
    }
}

/**
 * 文本查看框
 */
@Composable
fun TextDialog(
    text: String,
    onDismissRequest: () -> Unit,
    width: Dp,
    height: Dp,
    textColor: Color = Color.Unspecified,
    fontSize: TextUnit = TextUnit.Unspecified,
    fontStyle: FontStyle? = null,
    fontWeight: FontWeight? = null,
    fontFamily: FontFamily? = null,
    letterSpacing: TextUnit = TextUnit.Unspecified,
    textDecoration: TextDecoration? = null,
) {
    Dialog(onDismissRequest = onDismissRequest) {
        SelectionContainer {
            Text(
                text = text,
                modifier = Modifier
                    .size(width, height)
                    .background(Color.White)
                    .verticalScroll(rememberScrollState()),
                color = textColor,
                fontSize = fontSize,
                fontStyle = fontStyle,
                fontWeight = fontWeight,
                fontFamily = fontFamily,
                letterSpacing = letterSpacing,
                textDecoration = textDecoration
            )
        }
    }
}